home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / raid / devRaidInitiate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  36.8 KB  |  1,234 lines

  1. /* 
  2.  * devRaidInitiate.c --
  3.  *
  4.  *    This file implements the BlockDevice interface for homogeneous disk
  5.  *    arrays.
  6.  *
  7.  * Copyright 1989 Regents of the University of California
  8.  * All rights reserved.
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "sync.h"
  21. #include "sprite.h"
  22. #include "fs.h"
  23. #include "dev.h"
  24. #include "devBlockDevice.h"
  25. #include "devRaid.h"
  26. #include "semaphore.h"
  27. #include "stdlib.h"
  28. #include "devRaidUtil.h"
  29. #include "schedule.h"
  30. #include "devRaidProto.h"
  31.  
  32.  
  33. /*
  34.  *----------------------------------------------------------------------
  35.  *
  36.  * Raid_InitiateIORequests --
  37.  *
  38.  *    Initiates IO requests specified by reqControlPtr.
  39.  *    Calls doneProc with clientData, the number of requests that have
  40.  *    failed and a pointer to the last failed request when the IO is complete.
  41.  *
  42.  * Results:
  43.  *    None.
  44.  *
  45.  * Side effects:
  46.  *    The IO operations.
  47.  *
  48.  *----------------------------------------------------------------------
  49.  */
  50.  
  51. void blockIODoneProc();
  52. void nonInterruptLevelCallBackProc();
  53.  
  54. void 
  55. Raid_InitiateIORequests(reqControlPtr, doneProc, clientData)
  56.     RaidRequestControl    *reqControlPtr;
  57.     void           (*doneProc)();
  58.     ClientData         clientData;
  59. {
  60.     RaidIOControl    *IOControlPtr;
  61.     RaidBlockRequest    *reqPtr;
  62.     int             i;
  63.  
  64.     /*
  65.      * Initiate IO's.
  66.      */
  67. #ifdef TESTING
  68.     PrintRequests(reqControlPtr);
  69. #endif TESTING
  70.     IOControlPtr = Raid_MakeIOControl(doneProc, clientData);
  71.     IOControlPtr->numIO++;
  72.     for ( i = 0; i < reqControlPtr->numReq; i++ ) {
  73.     reqPtr = &reqControlPtr->reqPtr[i];
  74.     if (reqPtr->state == REQ_READY) {
  75.         reqPtr->state = REQ_PENDING;
  76.         MASTER_LOCK(&IOControlPtr->mutex);
  77.         IOControlPtr->numIO++;
  78.         MASTER_UNLOCK(&IOControlPtr->mutex);
  79.         reqPtr->devReq.doneProc   = blockIODoneProc;
  80.         reqPtr->devReq.clientData = (ClientData) IOControlPtr;
  81.         (void) Dev_BlockDeviceIO(
  82.             reqPtr->raidPtr->disk[reqPtr->col][reqPtr->row]->handlePtr,
  83.             (DevBlockDeviceRequest *) reqPtr);
  84.     }
  85.     }
  86.  
  87.     MASTER_LOCK(&IOControlPtr->mutex);
  88.     IOControlPtr->numIO--;
  89.     if (IOControlPtr->numIO == 0) {
  90.         MASTER_UNLOCK(&IOControlPtr->mutex);
  91.         IOControlPtr->doneProc(IOControlPtr->clientData,
  92.         IOControlPtr->numFailed, IOControlPtr->failedReqPtr);
  93.     Raid_FreeIOControl(IOControlPtr);
  94.     } else {
  95.         MASTER_UNLOCK(&IOControlPtr->mutex);
  96.     }
  97. }
  98.  
  99.  
  100. /*
  101.  *----------------------------------------------------------------------
  102.  *
  103.  * blockIODoneProc --
  104.  *
  105.  *    Callback procedure for Raid_InitiateIORequests.
  106.  *    This procedure is called once each time an individual IO reqeust
  107.  *    completes.
  108.  *
  109.  * Results:
  110.  *    None.
  111.  *
  112.  * Side effects:
  113.  *    Reports errors.
  114.  *
  115.  *----------------------------------------------------------------------
  116.  */
  117.  
  118. void
  119. blockIODoneProc(reqPtr, status, amountTransferred)
  120.     RaidBlockRequest    *reqPtr;
  121.     ReturnStatus     status;
  122.     int             amountTransferred;
  123. {
  124.     RaidIOControl    *IOControlPtr;
  125.     IOControlPtr = (RaidIOControl *) reqPtr->devReq.clientData;
  126.  
  127.     /*
  128.      * Check to see if disk has failed since request was initiated.
  129.      */
  130. /*
  131.     if (!IsValid(reqPtr->diskPtr,
  132.         ByteToSector(reqPtr->raidPtr, reqPtr->devReq.startAddress),
  133.         ByteToSector(reqPtr->raidPtr, reqPtr->devReq.bufferLen))) {
  134.     status = FAILURE;
  135.     }
  136. */
  137.  
  138.     reqPtr->status = status;
  139.     if (status != SUCCESS) {
  140.         reqPtr->state = REQ_FAILED;
  141.     Raid_ReportRequestError(reqPtr);
  142.     if (reqPtr->devReq.operation == FS_WRITE) {
  143.         Raid_FailDisk(reqPtr->raidPtr,
  144.             reqPtr->col, reqPtr->row, reqPtr->version);
  145.     }
  146.     } else {
  147.         reqPtr->state = REQ_COMPLETED;
  148.     }
  149.  
  150.     MASTER_LOCK(&IOControlPtr->mutex);
  151.     IOControlPtr->amountTransferred += amountTransferred;
  152.  
  153.     /*
  154.      * A Raid IO operation fails if any of the component operations fail.
  155.      * Therefore, don't overwrite status if a previous operation has failed.
  156.      */
  157.     if (status != SUCCESS) {
  158.         IOControlPtr->numFailed++;
  159.         IOControlPtr->failedReqPtr = reqPtr;
  160.     }
  161.  
  162.     /*
  163.      * Check if all component IO's done.
  164.      */
  165.     IOControlPtr->numIO--;
  166.     if (IOControlPtr->numIO == 0) {
  167.         MASTER_UNLOCK(&IOControlPtr->mutex);
  168.     /*
  169.      * this forces the call-back to happen at non-interrupt level
  170.      */
  171.     Proc_CallFunc(nonInterruptLevelCallBackProc,(ClientData)IOControlPtr,0);
  172.     } else {
  173.         MASTER_UNLOCK(&IOControlPtr->mutex);
  174.     }
  175. }
  176.  
  177.  
  178. /*
  179.  *----------------------------------------------------------------------
  180.  *
  181.  * nonInterruptLevelCallBackProc --
  182.  *
  183.  *    None-interrupt level callback procedure for Raid_InitiateIORequests.
  184.  *
  185.  * Results:
  186.  *    None.
  187.  *
  188.  * Side effects:
  189.  *
  190.  *----------------------------------------------------------------------
  191.  */
  192.  
  193. void
  194. nonInterruptLevelCallBackProc(IOControlPtr)
  195.     RaidIOControl    *IOControlPtr;
  196. {
  197.     IOControlPtr->doneProc(IOControlPtr->clientData,
  198.         IOControlPtr->numFailed, IOControlPtr->failedReqPtr);
  199.     Raid_FreeIOControl(IOControlPtr);
  200. }
  201.  
  202.  
  203. /*
  204.  *----------------------------------------------------------------------
  205.  *
  206.  * InitiateStripeIOFailure --
  207.  *
  208.  *    Causes the IO operation to fail, presumably because it can not
  209.  *    be completely (i.e. more than one disk in a group has failed.)
  210.  *
  211.  * Results:
  212.  *    None.
  213.  *
  214.  * Side effects:
  215.  *    None.
  216.  *
  217.  *----------------------------------------------------------------------
  218.  */
  219.  
  220. static void stripeIODoneProc();
  221.  
  222. static void
  223. InitiateStripeIOFailure(stripeIOControlPtr)
  224.     RaidStripeIOControl    *stripeIOControlPtr;
  225. {
  226.     stripeIODoneProc(stripeIOControlPtr, 2);
  227. }
  228.  
  229.  
  230. /*
  231.  *----------------------------------------------------------------------
  232.  *
  233.  * InitiateStripeWrite --
  234.  *
  235.  *    Initiates a stripe write (i.e. an IO that does not span stripe
  236.  *    boundaries) via either Raid_InitiateIORequests, InitiateReconstructWrite
  237.  *    or InitiateReadModifyWrite.
  238.  *    Sets up the recovery procedure if recovery is possible.  Note that
  239.  *    the recovery procedure for InitiateReconstructWrite is
  240.  *    InitiateReadModifyWrite and visa versa.
  241.  *    Calls callback procedure specified by stripeIOControlPtr with
  242.  *    stripeIOControlPtr, number of requests that have failed and a
  243.  *    pointer to the last failed request, when the IO is complete.
  244.  *
  245.  * Results:
  246.  *    None.
  247.  *
  248.  * Side effects:
  249.  *    The IO operation.
  250.  *
  251.  *----------------------------------------------------------------------
  252.  */
  253.  
  254. static void InitiateSplitStripeWrite();
  255. static void InitiateReadModifyWrite();
  256. static void InitiateReconstructWrite();
  257. static void oldInfoReadDoneProc();
  258. static void stripeWriteDoneProc();
  259.  
  260. static void
  261. InitiateStripeWrite(stripeIOControlPtr)
  262.     RaidStripeIOControl    *stripeIOControlPtr;
  263. {
  264.     Raid        *raidPtr       = stripeIOControlPtr->raidPtr;
  265.     unsigned         firstSector   = stripeIOControlPtr->firstSector;
  266.     unsigned         nthSector     = stripeIOControlPtr->nthSector;
  267.     Address         buffer        = stripeIOControlPtr->buffer;
  268.     int             ctrlData      = stripeIOControlPtr->ctrlData;
  269.     RaidRequestControl    *reqControlPtr = stripeIOControlPtr->reqControlPtr;
  270.     char        *parityBuf     = stripeIOControlPtr->parityBuf;
  271.  
  272.     /*
  273.      * Check to see if parity disk has failed.
  274.      */
  275.     reqControlPtr->numReq = reqControlPtr->numFailed = 0;
  276.     AddRaidParityRequest(reqControlPtr, raidPtr, FS_READ,
  277.         firstSector, parityBuf, ctrlData);
  278.     if (reqControlPtr->numFailed > 0) {
  279.     /*
  280.      * If parity disk has failed, just write the data.
  281.      */
  282.     reqControlPtr->numReq = reqControlPtr->numFailed = 0;
  283.     AddRaidDataRequests(reqControlPtr, raidPtr, FS_WRITE,
  284.         firstSector, nthSector, buffer, ctrlData);
  285.     if (reqControlPtr->numFailed == 0) {
  286.         Raid_InitiateIORequests(stripeIOControlPtr->reqControlPtr,
  287.             stripeIODoneProc, (ClientData) stripeIOControlPtr);
  288.     } else {
  289.         InitiateStripeIOFailure(stripeIOControlPtr);
  290.     }
  291.     } else if (nthSector-firstSector < raidPtr->dataSectorsPerStripe/2) {
  292.     /*
  293.      * If less than half of the stripe is being written, do a
  294.      * read modify write.
  295.      */
  296.     stripeIOControlPtr->recoverProc = InitiateReconstructWrite;
  297.     InitiateReadModifyWrite(stripeIOControlPtr);
  298.     } else {
  299.     /*
  300.      * If half or more of the stripe is being written, do a
  301.      * reconstruct write.
  302.      */
  303.     stripeIOControlPtr->recoverProc = InitiateReadModifyWrite;
  304.     InitiateReconstructWrite(stripeIOControlPtr);
  305.     }
  306. }
  307.  
  308.  
  309. /*
  310.  *----------------------------------------------------------------------
  311.  *
  312.  * InitiateSplitStripeWrite --
  313.  *
  314.  *    If a write request which covers multiple stripe units fails durring
  315.  *    the read phase and the failed component is not a full stripe unit,
  316.  *    It is necessary to do both a read-modify-write and a reconstruct write
  317.  *    in order to complete the entire request.
  318.  *    Note: StripeIOControlPtr->failedReqPtr is assumed to point to the data
  319.  *    part of the failed request.
  320.  *
  321.  * Results:
  322.  *    None.
  323.  *
  324.  * Side effects:
  325.  *    The IO operation.
  326.  *
  327.  *----------------------------------------------------------------------
  328.  */
  329.  
  330. static void
  331. InitiateSplitStripeWrite(stripeIOControlPtr)
  332.     RaidStripeIOControl    *stripeIOControlPtr;
  333. {
  334.     Raid        *raidPtr       = stripeIOControlPtr->raidPtr;
  335.     unsigned         firstSector   = stripeIOControlPtr->firstSector;
  336.     unsigned         nthSector     = stripeIOControlPtr->nthSector;
  337. /*    Address         buffer        = stripeIOControlPtr->buffer; */
  338.     int             ctrlData      = stripeIOControlPtr->ctrlData;
  339.     RaidRequestControl    *reqControlPtr = stripeIOControlPtr->reqControlPtr;
  340.     char        *parityBuf     = stripeIOControlPtr->parityBuf;
  341.     char        *readBuf       = stripeIOControlPtr->readBuf;
  342.     int             failedOff     = (int) StripeUnitOffset(raidPtr,
  343.           stripeIOControlPtr->reqControlPtr->failedReqPtr->devReq.startAddress);
  344.     int             failedLen     =
  345.            stripeIOControlPtr->reqControlPtr->failedReqPtr->devReq.bufferLen;
  346.     int             rangeOff;
  347.     int             rangeLen;
  348.  
  349. #ifdef TESTING
  350.     printf("InitiateSplitStripeWrite\n");
  351. #endif TESTING
  352.     /*
  353.      * 'Deduce' data part of failed request.
  354.      */
  355.     if (stripeIOControlPtr->recoverProc == (void(*)())InitiateReadModifyWrite) {
  356.     failedOff = StripeUnitOffset(raidPtr, failedOff + failedLen);
  357.     failedLen = raidPtr->bytesPerStripeUnit - failedLen;
  358.     }
  359.     rangeOff = StripeUnitOffset(raidPtr, failedOff + failedLen);
  360.     rangeLen = raidPtr->bytesPerStripeUnit - failedLen;
  361.  
  362.     stripeIOControlPtr->recoverProc = InitiateStripeIOFailure;
  363.     stripeIOControlPtr->rangeOff = 0;
  364.     stripeIOControlPtr->rangeLen = raidPtr->bytesPerStripeUnit;
  365.     reqControlPtr->numReq = reqControlPtr->numFailed = 0;
  366.     /*
  367.      * reconstructWrite strip
  368.      */
  369.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  370.         FirstSectorOfStripe(raidPtr, firstSector), firstSector,
  371.         readBuf, ctrlData,
  372.         failedOff, failedLen);
  373.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  374.         nthSector, NthSectorOfStripe(raidPtr, firstSector),
  375.         readBuf + SectorToByte(raidPtr,
  376.                 firstSector - FirstSectorOfStripe(raidPtr, firstSector)),
  377.         ctrlData, failedOff, failedLen);
  378.     /*
  379.      * RMW strip
  380.      */
  381.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  382.         firstSector, nthSector, readBuf + SectorToByte(raidPtr,
  383.             raidPtr->dataSectorsPerStripe - (nthSector-firstSector)),
  384.         ctrlData, rangeOff, rangeLen);
  385.     Raid_AddParityRangeRequest(reqControlPtr, raidPtr, FS_READ,
  386.         firstSector, parityBuf, ctrlData,
  387.         rangeOff, rangeLen);
  388.     if (reqControlPtr->numFailed == 0) {
  389.     Raid_InitiateIORequests(reqControlPtr,
  390.         oldInfoReadDoneProc, (ClientData) stripeIOControlPtr);
  391.     } else {
  392.     stripeIOControlPtr->recoverProc(stripeIOControlPtr);
  393.     }
  394. }
  395.  
  396.  
  397. /*
  398.  *----------------------------------------------------------------------
  399.  *
  400.  * InitiateReadModifyWrite --
  401.  *
  402.  *    Initiates a read modify write.  (i.e. read old data and old parity,
  403.  *    computes the new parity and then writes the new data and new parity)
  404.  *    Calls the recovery procedure if a read modify wirte can not complete.
  405.  *    Calls callback procedure specified by stripeIOControlPtr with
  406.  *    stripeIOControlPtr, number of requests that have failed and a
  407.  *    pointer to the last failed request, when the IO is complete.
  408.  *
  409.  * Results:
  410.  *    None.
  411.  *
  412.  * Side effects:
  413.  *    The IO operation.
  414.  *
  415.  *----------------------------------------------------------------------
  416.  */
  417.  
  418. static void
  419. InitiateReadModifyWrite(stripeIOControlPtr)
  420.     RaidStripeIOControl    *stripeIOControlPtr;
  421. {
  422.     Raid        *raidPtr       = stripeIOControlPtr->raidPtr;
  423.     unsigned         firstSector   = stripeIOControlPtr->firstSector;
  424.     unsigned         nthSector     = stripeIOControlPtr->nthSector;
  425. /*    Address         buffer        = stripeIOControlPtr->buffer; */
  426.     int             ctrlData      = stripeIOControlPtr->ctrlData;
  427.     RaidRequestControl    *reqControlPtr = stripeIOControlPtr->reqControlPtr;
  428.     char        *parityBuf     = stripeIOControlPtr->parityBuf;
  429.     char        *readBuf       = stripeIOControlPtr->readBuf;
  430.     void           (*recoverProc)()= stripeIOControlPtr->recoverProc;
  431.  
  432. #ifdef TESTING
  433.     printf("InitiateReadModifyWrite\n");
  434. #endif TESTING
  435.     reqControlPtr->numReq = reqControlPtr->numFailed = 0;
  436.     AddRaidDataRequests(reqControlPtr, raidPtr, FS_READ,
  437.         firstSector, nthSector, readBuf, ctrlData);
  438.     if (reqControlPtr->numReq == 1) {
  439.     stripeIOControlPtr->rangeOff =
  440.         reqControlPtr->reqPtr[0].devReq.startAddress;
  441.     stripeIOControlPtr->rangeLen =
  442.         reqControlPtr->reqPtr[0].devReq.bufferLen;
  443.     } else {
  444.     stripeIOControlPtr->rangeOff = 0;
  445.     stripeIOControlPtr->rangeLen = raidPtr->bytesPerStripeUnit;
  446.     }
  447.     Raid_AddParityRangeRequest(reqControlPtr, raidPtr, FS_READ,
  448.         firstSector, parityBuf, ctrlData,
  449.         stripeIOControlPtr->rangeOff, stripeIOControlPtr->rangeLen);
  450.     if (reqControlPtr->numFailed == 0) {
  451.     Raid_InitiateIORequests(reqControlPtr,
  452.         oldInfoReadDoneProc, (ClientData) stripeIOControlPtr);
  453.     } else {
  454.     /*
  455.      * If the request covers multiple stripe units and is not stripe unit
  456.      * aligned, check to see if the failed request is a partial
  457.      * stripe unit.  If it is, then both a read-modify-write and
  458.      * a reconstruct write is necessary to complete the request.
  459.      */
  460.     DevBlockDeviceRequest *devReqPtr = &reqControlPtr->failedReqPtr->devReq;
  461.     if (stripeIOControlPtr->rangeLen == raidPtr->bytesPerStripeUnit &&
  462.         devReqPtr->bufferLen != raidPtr->bytesPerStripeUnit &&
  463.         recoverProc != (void (*)()) InitiateStripeIOFailure) {
  464.         stripeIOControlPtr->recoverProc = InitiateStripeIOFailure;
  465.         InitiateSplitStripeWrite(stripeIOControlPtr);
  466.     } else {
  467.         stripeIOControlPtr->recoverProc = InitiateStripeIOFailure;
  468.         recoverProc(stripeIOControlPtr);
  469.     }
  470.     }
  471. }
  472.  
  473.  
  474. /*
  475.  *----------------------------------------------------------------------
  476.  *
  477.  * InitiateReconstructWrite --
  478.  *
  479.  *    Initiates a reconstruct write.  (i.e. read rest of stripe if any
  480.  *    computes the new parity and then writes the new data and new parity)
  481.  *    Calls the recovery procedure if a read modify wirte can not complete.
  482.  *    Calls callback procedure specified by stripeIOControlPtr with
  483.  *    stripeIOControlPtr, number of requests that have failed and a
  484.  *    pointer to the last failed request, when the IO is complete.
  485.  *
  486.  * Results:
  487.  *    None.
  488.  *
  489.  * Side effects:
  490.  *    The IO operation.
  491.  *
  492.  *----------------------------------------------------------------------
  493.  */
  494.  
  495. static void
  496. InitiateReconstructWrite(stripeIOControlPtr)
  497.     RaidStripeIOControl    *stripeIOControlPtr;
  498. {
  499.     Raid        *raidPtr       = stripeIOControlPtr->raidPtr;
  500.     unsigned         firstSector   = stripeIOControlPtr->firstSector;
  501.     unsigned         nthSector     = stripeIOControlPtr->nthSector;
  502. /*    Address         buffer        = stripeIOControlPtr->buffer; */
  503.     int             ctrlData      = stripeIOControlPtr->ctrlData;
  504.     RaidRequestControl    *reqControlPtr = stripeIOControlPtr->reqControlPtr;
  505. /*    char        *parityBuf     = stripeIOControlPtr->parityBuf; */
  506.     char        *readBuf       = stripeIOControlPtr->readBuf;
  507.     void           (*recoverProc)()= stripeIOControlPtr->recoverProc;
  508.  
  509.     /*
  510.      * If writing only one stripe unit, range restrict the write.
  511.      */
  512. #ifdef TESTING
  513.     printf("InitiateReconstructWrite\n");
  514. #endif TESTING
  515.     if (SectorToStripeUnitID(raidPtr, firstSector) ==
  516.         SectorToStripeUnitID(raidPtr, nthSector-1)) {
  517.     stripeIOControlPtr->rangeOff = SectorToByte(raidPtr, firstSector);
  518.         stripeIOControlPtr->rangeLen =
  519.         SectorToByte(raidPtr, nthSector-firstSector);
  520.     } else {
  521.     stripeIOControlPtr->rangeOff = 0;
  522.     stripeIOControlPtr->rangeLen = raidPtr->bytesPerStripeUnit;
  523.     }
  524.     reqControlPtr->numReq = reqControlPtr->numFailed = 0;
  525.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  526.         FirstSectorOfStripe(raidPtr, firstSector), firstSector,
  527.         readBuf, ctrlData,
  528.         stripeIOControlPtr->rangeOff, stripeIOControlPtr->rangeLen);
  529.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  530.         nthSector, NthSectorOfStripe(raidPtr, firstSector),
  531.         readBuf + SectorToByte(raidPtr,
  532.                 firstSector - FirstSectorOfStripe(raidPtr, firstSector)),
  533.         ctrlData,stripeIOControlPtr->rangeOff,stripeIOControlPtr->rangeLen);
  534.     if (reqControlPtr->numFailed == 0) {
  535.     Raid_InitiateIORequests(stripeIOControlPtr->reqControlPtr,
  536.         oldInfoReadDoneProc, (ClientData) stripeIOControlPtr);
  537.     } else {
  538.     /*
  539.      * If the request covers multiple stripe units and is not stripe unit
  540.      * aligned, check to see if the failed request is a partial
  541.      * stripe unit.  If it is, then both a read-modify-write and
  542.      * a reconstruct write is necessary to complete the request.
  543.      */
  544.     DevBlockDeviceRequest *devReqPtr = &reqControlPtr->failedReqPtr->devReq;
  545.     if (stripeIOControlPtr->rangeLen == raidPtr->bytesPerStripeUnit &&
  546.         devReqPtr->bufferLen != raidPtr->bytesPerStripeUnit &&
  547.         recoverProc != (void(*)()) InitiateStripeIOFailure) {
  548.         InitiateSplitStripeWrite(stripeIOControlPtr);
  549.     } else {
  550.         stripeIOControlPtr->recoverProc = InitiateStripeIOFailure;
  551.         recoverProc(stripeIOControlPtr);
  552.     }
  553.     }
  554. }
  555.  
  556.  
  557. /*
  558.  *----------------------------------------------------------------------
  559.  *
  560.  * oldInfoReadDoneProc --
  561.  *
  562.  *    Callback procedure for InitiateReadModifyWrite and
  563.  *    InitiateReconstructWrite.
  564.  *    This procedure is called after the old data and parity have been read
  565.  *    in the process of writing new data.
  566.  *    If an error has occured, the recovery procedure is called.
  567.  *
  568.  * Results:
  569.  *    None.
  570.  *
  571.  * Side effects:
  572.  *    IO operations.
  573.  *
  574.  *----------------------------------------------------------------------
  575.  */
  576.  
  577. static void
  578. oldInfoReadDoneProc(stripeIOControlPtr, numFailed, failedReqPtr)
  579.     RaidStripeIOControl    *stripeIOControlPtr;
  580.     int              numFailed;
  581.     RaidBlockRequest    *failedReqPtr;
  582. {
  583.     Raid        *raidPtr    = stripeIOControlPtr->raidPtr;
  584.     RaidRequestControl    *reqControlPtr    = stripeIOControlPtr->reqControlPtr;
  585.  
  586.     if (numFailed == 0) {
  587.     char            *parityBuf;
  588.  
  589. #ifndef NODATA
  590.         parityBuf = Malloc((unsigned) raidPtr->bytesPerStripeUnit);
  591.     bzero(parityBuf, raidPtr->bytesPerStripeUnit);
  592. #endif
  593.  
  594.     Raid_XorRangeRequests(reqControlPtr,
  595.         raidPtr, parityBuf,
  596.         stripeIOControlPtr->rangeOff, stripeIOControlPtr->rangeLen);
  597.         reqControlPtr->numReq = 0;
  598.         reqControlPtr->numFailed = 0;
  599.         Raid_AddDataRangeRequests(reqControlPtr,
  600.         raidPtr, FS_WRITE,
  601.         stripeIOControlPtr->firstSector, stripeIOControlPtr->nthSector,
  602.                 stripeIOControlPtr->buffer, stripeIOControlPtr->ctrlData,
  603.         stripeIOControlPtr->rangeOff, stripeIOControlPtr->rangeLen);
  604.     /*
  605.      * Raid_XorRangeRequests will not xor failed requests so we have
  606.      * to change its state to REQ_COMPLETED to make it xor the new data.
  607.      */
  608.     if (reqControlPtr->numFailed > 0) {
  609.         reqControlPtr->failedReqPtr->state = REQ_COMPLETED;
  610.     }
  611.     Raid_XorRangeRequests(reqControlPtr,
  612.         raidPtr, parityBuf,
  613.         stripeIOControlPtr->rangeOff, stripeIOControlPtr->rangeLen);
  614. #ifndef NODATA
  615.     Free(stripeIOControlPtr->parityBuf);
  616. #endif
  617.     stripeIOControlPtr->parityBuf = parityBuf;
  618.         Raid_AddParityRangeRequest(reqControlPtr,
  619.         raidPtr, FS_WRITE,
  620.             stripeIOControlPtr->firstSector, stripeIOControlPtr->parityBuf,
  621.         stripeIOControlPtr->ctrlData,
  622.         stripeIOControlPtr->rangeOff, stripeIOControlPtr->rangeLen);
  623.     switch (reqControlPtr->numFailed) {
  624.     case 0:
  625.             Raid_InitiateIORequests(reqControlPtr,
  626.             stripeWriteDoneProc, (ClientData) stripeIOControlPtr);
  627.         break;
  628.     case 1:
  629.             Raid_InitiateIORequests(reqControlPtr,
  630.             stripeIODoneProc, (ClientData) stripeIOControlPtr);
  631.         break;
  632.     default:
  633.         InitiateStripeIOFailure(stripeIOControlPtr);
  634.         break;
  635.     }
  636.     } else {
  637.         void       (*recoverProc)() = stripeIOControlPtr->recoverProc;
  638.     reqControlPtr->failedReqPtr = failedReqPtr;
  639.     /*
  640.      * If the request covers multiple stripe units and is not stripe unit
  641.      * aligned, check to see if the failed request is a partial
  642.      * stripe unit.  If it is, then both a read-modify-write and
  643.      * a reconstruct write is necessary to complete the request.
  644.      */
  645.     if (stripeIOControlPtr->rangeLen == raidPtr->bytesPerStripeUnit &&
  646.         failedReqPtr->devReq.bufferLen != raidPtr->bytesPerStripeUnit &&
  647.         recoverProc != (void (*)()) InitiateStripeIOFailure) {
  648.         InitiateSplitStripeWrite(stripeIOControlPtr);
  649.     } else {
  650.         stripeIOControlPtr->recoverProc = InitiateStripeIOFailure;
  651.         recoverProc(stripeIOControlPtr);
  652.     }
  653.     }
  654. }
  655.  
  656.  
  657. /*
  658.  *----------------------------------------------------------------------
  659.  *
  660.  * stripeWriteDoneProc --
  661.  *
  662.  *    Callback procedure for oldInfoReadDoneProc.
  663.  *    This procedure is called after the new data and parity have
  664.  *    been written.
  665.  *    Since one of the writes is redundant, the IO is considered to have
  666.  *    succeeded as long as the number of failures is less than or equal
  667.  *    to one.
  668.  *
  669.  * Results:
  670.  *    None.
  671.  *
  672.  * Side effects:
  673.  *    None.
  674.  *
  675.  *----------------------------------------------------------------------
  676.  */
  677.  
  678. static void
  679. stripeWriteDoneProc(stripeIOControlPtr, numFailed)
  680.     RaidStripeIOControl    *stripeIOControlPtr;
  681.     int             numFailed;
  682. {
  683.     if (numFailed <= 1) {
  684.     stripeIODoneProc(stripeIOControlPtr, 0);
  685.     } else {
  686.     stripeIODoneProc(stripeIOControlPtr, numFailed);
  687.     }
  688. }
  689.  
  690.  
  691. /*
  692.  *----------------------------------------------------------------------
  693.  *
  694.  * InitiateStripeRead --
  695.  *
  696.  *    Initiates a stripe read (i.e. an IO that does not span stripe
  697.  *    boundaries).
  698.  *    Calls callback procedure specified by stripeIOControlPtr with
  699.  *    stripeIOControlPtr, number of requests that have failed and a
  700.  *    pointer to the last failed request, when the IO is complete.
  701.  *
  702.  * Results:
  703.  *    None.
  704.  *
  705.  * Side effects:
  706.  *    The IO operation.
  707.  *
  708.  *----------------------------------------------------------------------
  709.  */
  710.  
  711. static void stripeReadDoneProc();
  712. static void reconstructStripeReadDoneProc();
  713. static void InitiateReconstructRead();
  714.  
  715. static void
  716. InitiateStripeRead(stripeIOControlPtr)
  717.     RaidStripeIOControl    *stripeIOControlPtr;
  718. {
  719.     Raid        *raidPtr       = stripeIOControlPtr->raidPtr;
  720.     unsigned         firstSector   = stripeIOControlPtr->firstSector;
  721.     unsigned         nthSector     = stripeIOControlPtr->nthSector;
  722.     Address         buffer        = stripeIOControlPtr->buffer;
  723.     int             ctrlData      = stripeIOControlPtr->ctrlData;
  724.     RaidRequestControl    *reqControlPtr = stripeIOControlPtr->reqControlPtr;
  725. /*    char        *parityBuf     = stripeIOControlPtr->parityBuf; */
  726. /*    char        *readBuf       = stripeIOControlPtr->readBuf; */
  727.  
  728.     reqControlPtr->numReq = reqControlPtr->numFailed = 0;
  729.     AddRaidDataRequests(reqControlPtr, raidPtr, FS_READ,
  730.         firstSector, nthSector, buffer, ctrlData);
  731.     switch (reqControlPtr->numFailed) {
  732.     case 0:
  733.         Raid_InitiateIORequests(reqControlPtr,
  734.         stripeReadDoneProc, (ClientData) stripeIOControlPtr);
  735.     break;
  736.     case 1:
  737.     InitiateReconstructRead(stripeIOControlPtr);
  738.     break;
  739.     default:
  740.     InitiateStripeIOFailure(stripeIOControlPtr);
  741.     break;
  742.     }
  743. }
  744.  
  745.  
  746. /*
  747.  *----------------------------------------------------------------------
  748.  *
  749.  * stripeReadDoneProc --
  750.  *
  751.  *    Callback procedure for InitiateStripeRead.
  752.  *
  753.  * Results:
  754.  *    None.
  755.  *
  756.  * Side effects:
  757.  *    None.
  758.  *
  759.  *----------------------------------------------------------------------
  760.  */
  761.  
  762. static void
  763. stripeReadDoneProc(stripeIOControlPtr, numFailed, failedReqPtr)
  764.     RaidStripeIOControl    *stripeIOControlPtr;
  765.     int             numFailed;
  766.     RaidBlockRequest    *failedReqPtr;
  767. {
  768.     switch (numFailed) {
  769.     case 0:
  770.     stripeIODoneProc(stripeIOControlPtr, numFailed);
  771.     break;
  772.     case 1:
  773.     stripeIOControlPtr->reqControlPtr->failedReqPtr = failedReqPtr;
  774.     InitiateReconstructRead(stripeIOControlPtr);
  775.     break;
  776.     default:
  777.     stripeIODoneProc(stripeIOControlPtr, numFailed);
  778.     break;
  779.     }
  780. }
  781.  
  782.  
  783. /*
  784.  *----------------------------------------------------------------------
  785.  *
  786.  * InitiateReconstructRead --
  787.  *
  788.  *    Initiates a reconstruct read (i.e. computes requested data by reading
  789.  *    the rest of the stripe and parity).
  790.  *    Calls callback procedure specified by stripeIOControlPtr with
  791.  *    stripeIOControlPtr, number of requests that have failed and a
  792.  *    pointer to the last failed request, when the IO is complete.
  793.  *
  794.  * Results:
  795.  *    None.
  796.  *
  797.  * Side effects:
  798.  *    The IO operation.
  799.  *
  800.  *----------------------------------------------------------------------
  801.  */
  802.  
  803. static void
  804. InitiateReconstructRead(stripeIOControlPtr)
  805.     RaidStripeIOControl    *stripeIOControlPtr;
  806. {
  807.     Raid        *raidPtr       = stripeIOControlPtr->raidPtr;
  808.     unsigned         firstSector   = stripeIOControlPtr->firstSector;
  809.     unsigned         nthSector     = stripeIOControlPtr->nthSector;
  810. /*    Address         buffer        = stripeIOControlPtr->buffer; */
  811.     int             ctrlData      = stripeIOControlPtr->ctrlData;
  812.     RaidRequestControl    *reqControlPtr = stripeIOControlPtr->reqControlPtr;
  813.     char        *parityBuf     = stripeIOControlPtr->parityBuf;
  814.     char        *readBuf       = stripeIOControlPtr->readBuf;
  815.  
  816.     reqControlPtr->numFailed = 0;
  817.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  818.         FirstSectorOfStripe(raidPtr, firstSector), firstSector,
  819.         readBuf, ctrlData,
  820.         (int) reqControlPtr->failedReqPtr->devReq.startAddress,
  821.         reqControlPtr->failedReqPtr->devReq.bufferLen);
  822.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  823.         nthSector, NthSectorOfStripe(raidPtr, firstSector),
  824.         readBuf + SectorToByte(raidPtr,
  825.             firstSector - FirstSectorOfStripe(raidPtr, firstSector)),
  826.         ctrlData,
  827.         (int) reqControlPtr->failedReqPtr->devReq.startAddress,
  828.         reqControlPtr->failedReqPtr->devReq.bufferLen);
  829.     Raid_AddParityRangeRequest(reqControlPtr, raidPtr, FS_READ,
  830.         firstSector, parityBuf, ctrlData,
  831.         (int) reqControlPtr->failedReqPtr->devReq.startAddress,
  832.         reqControlPtr->failedReqPtr->devReq.bufferLen);
  833.     switch (reqControlPtr->numFailed) {
  834.     case 0:
  835.     Raid_InitiateIORequests(stripeIOControlPtr->reqControlPtr,
  836.         reconstructStripeReadDoneProc, (ClientData) stripeIOControlPtr);
  837.     break;
  838.     default:
  839.     InitiateStripeIOFailure(stripeIOControlPtr);
  840.     break;
  841.     }
  842. }
  843.  
  844.  
  845. /*
  846.  *----------------------------------------------------------------------
  847.  *
  848.  * reconstructStripeReadDoneProc --
  849.  *
  850.  *    Callback procedure for InitiateReconstructRead.
  851.  *
  852.  * Results:
  853.  *    None.
  854.  *
  855.  * Side effects:
  856.  *    None.
  857.  *
  858.  *----------------------------------------------------------------------
  859.  */
  860.  
  861. static void
  862. reconstructStripeReadDoneProc(stripeIOControlPtr, numFailed)
  863.     RaidStripeIOControl    *stripeIOControlPtr;
  864.     int             numFailed;
  865. {
  866.     RaidBlockRequest    *failedReqPtr;
  867.     failedReqPtr = stripeIOControlPtr->reqControlPtr->failedReqPtr;
  868.  
  869.     switch (numFailed) {
  870.     case 0:
  871. #ifndef NODATA
  872.     bzero(failedReqPtr->devReq.buffer, failedReqPtr->devReq.bufferLen);
  873. #endif
  874.     Raid_XorRangeRequests(stripeIOControlPtr->reqControlPtr,
  875.         stripeIOControlPtr->raidPtr, failedReqPtr->devReq.buffer,
  876.         (int) failedReqPtr->devReq.startAddress,
  877.         failedReqPtr->devReq.bufferLen);
  878.     stripeIODoneProc(stripeIOControlPtr, numFailed);
  879.     break;
  880.     default:
  881.     stripeIODoneProc(stripeIOControlPtr, numFailed);
  882.     break;
  883.     }
  884. }
  885.  
  886.  
  887. /*
  888.  *----------------------------------------------------------------------
  889.  *
  890.  * InitiateSingleStripeIO --
  891.  *
  892.  *    Initiates a single stripe IO request.
  893.  *    Locks stripe, does IO and then unlocks the stripe in order to
  894.  *    guarantee the consistency of parity.  (The unlocking is done in the
  895.  *    associated callback procedure.)
  896.  *    Calls doneProc with clientData, status and the amount transferreed
  897.  *    as arguments when the IO is completed.
  898.  *
  899.  * Results:
  900.  *    None.
  901.  *
  902.  * Side effects:
  903.  *    The IO operation.
  904.  *    Locks stripe.
  905.  *
  906.  *----------------------------------------------------------------------
  907.  */
  908.  
  909. static void stripeIODoneProc();
  910.  
  911. static void 
  912. InitiateSingleStripeIO(raidPtr, operation, firstSector, nthSector,
  913.                 buffer, doneProc, clientData, ctrlData)
  914.     Raid       *raidPtr;
  915.     int        operation;
  916.     unsigned     firstSector, nthSector;
  917.     Address      buffer;
  918.     void      (*doneProc)();
  919.     ClientData    clientData;
  920.     int         ctrlData;
  921. {
  922.     RaidStripeIOControl    *stripeIOControlPtr;
  923.     stripeIOControlPtr = Raid_MakeStripeIOControl(raidPtr, operation,
  924.         firstSector, nthSector, buffer, doneProc, clientData, ctrlData);
  925.  
  926.     switch (stripeIOControlPtr->operation) {
  927.     case FS_READ:
  928.     Raid_SLockStripe(raidPtr,
  929.         SectorToStripeID(raidPtr, stripeIOControlPtr->firstSector));
  930.     InitiateStripeRead(stripeIOControlPtr);
  931.     break;
  932.     case FS_WRITE:
  933.     Raid_XLockStripe(raidPtr,
  934.         SectorToStripeID(raidPtr, stripeIOControlPtr->firstSector));
  935.     InitiateStripeWrite(stripeIOControlPtr);
  936.     break;
  937.     }
  938. }
  939.  
  940.  
  941. /*
  942.  *----------------------------------------------------------------------
  943.  *
  944.  * stripeIODoneProc --
  945.  *
  946.  *    Callback procedure for InitiateSingleStripeIO.
  947.  *
  948.  * Results:
  949.  *    None.
  950.  *
  951.  * Side effects:
  952.  *    Unlocks stripe.
  953.  *
  954.  *----------------------------------------------------------------------
  955.  */
  956.  
  957. static void
  958. stripeIODoneProc(stripeIOControlPtr, numFailed)
  959.     RaidStripeIOControl    *stripeIOControlPtr;
  960.     int             numFailed;
  961. {
  962.     if (stripeIOControlPtr->operation == FS_WRITE) {
  963.     Raid_XUnlockStripe(stripeIOControlPtr->raidPtr,
  964.         SectorToStripeID(stripeIOControlPtr->raidPtr,
  965.         stripeIOControlPtr->firstSector));
  966.     } else {
  967.     Raid_SUnlockStripe(stripeIOControlPtr->raidPtr,
  968.         SectorToStripeID(stripeIOControlPtr->raidPtr,
  969.         stripeIOControlPtr->firstSector));
  970.     }
  971.     if (numFailed == 0) {
  972.         stripeIOControlPtr->doneProc(stripeIOControlPtr->clientData, SUCCESS, 
  973.         SectorToByte(stripeIOControlPtr->raidPtr,
  974.             stripeIOControlPtr->nthSector -
  975.             stripeIOControlPtr->firstSector));
  976.     } else {
  977.         stripeIOControlPtr->doneProc(stripeIOControlPtr->clientData, FAILURE,0);
  978.     }
  979.     Raid_FreeStripeIOControl(stripeIOControlPtr);
  980. }
  981.  
  982.  
  983. /*
  984.  *----------------------------------------------------------------------
  985.  *
  986.  * Raid_InitiateStripeIOs --
  987.  *
  988.  *    Breaks IO requests into single stripe requests.
  989.  *    Calls doneProc with clientData, status and the amount transferreed
  990.  *    as arguments when the IO is completed.
  991.  *
  992.  * Results:
  993.  *    The return code from queuing the I/O operation.
  994.  *
  995.  * Side effects:
  996.  *    The IO operation.
  997.  *
  998.  *----------------------------------------------------------------------
  999.  */
  1000.  
  1001. static void singleStripeIODoneProc();
  1002.  
  1003. void 
  1004. Raid_InitiateStripeIOs(raidPtr, operation, firstSector, nthSector,
  1005.                 buffer, doneProc, clientData, ctrlData)
  1006.     Raid       *raidPtr;
  1007.     int        operation;
  1008.     unsigned     firstSector, nthSector;
  1009.     Address      buffer;
  1010.     void      (*doneProc)();
  1011.     ClientData    clientData;
  1012.     int         ctrlData;
  1013. {
  1014.     RaidIOControl       *IOControlPtr;
  1015.     int            numSectorsToTransfer;
  1016.     unsigned            currentSector;
  1017.  
  1018.     /*
  1019.      * Break up IO request into stripe requests.
  1020.      */
  1021.     Raid_BeginUse(raidPtr);
  1022.     IOControlPtr = Raid_MakeIOControl(doneProc, clientData);
  1023.     IOControlPtr->raidPtr = raidPtr;
  1024.     IOControlPtr->numIO++;
  1025.     currentSector = firstSector;
  1026.     while ( currentSector < nthSector ) {
  1027.         numSectorsToTransfer = MIN( raidPtr->dataSectorsPerStripe -
  1028.                 currentSector%raidPtr->dataSectorsPerStripe,
  1029.                 nthSector - currentSector );
  1030.  
  1031.         MASTER_LOCK(&IOControlPtr->mutex);
  1032.     IOControlPtr->numIO++;
  1033.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1034.  
  1035.         InitiateSingleStripeIO(raidPtr, operation,
  1036.                  currentSector, currentSector+numSectorsToTransfer, buffer,
  1037.                  singleStripeIODoneProc, (ClientData) IOControlPtr,
  1038.                  ctrlData);
  1039.  
  1040.         currentSector += numSectorsToTransfer;
  1041.     buffer += SectorToByte(raidPtr, numSectorsToTransfer);
  1042.     }
  1043.  
  1044.     MASTER_LOCK(&IOControlPtr->mutex);
  1045.     IOControlPtr->numIO--;
  1046.     if (IOControlPtr->numIO == 0) {
  1047.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1048.         IOControlPtr->doneProc(IOControlPtr->clientData,
  1049.         IOControlPtr->status, IOControlPtr->amountTransferred);
  1050.     Raid_FreeIOControl(IOControlPtr);
  1051.     Raid_EndUse(IOControlPtr->raidPtr);
  1052.     } else {
  1053.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1054.     }
  1055. }
  1056.  
  1057.  
  1058. /*
  1059.  *----------------------------------------------------------------------
  1060.  *
  1061.  * singleStripeIODoneProc --
  1062.  *
  1063.  *    Callback procedure for Raid_InitiateStripeIOs.
  1064.  *
  1065.  * Results:
  1066.  *    None.
  1067.  *
  1068.  * Side effects:
  1069.  *    None.
  1070.  *
  1071.  *----------------------------------------------------------------------
  1072.  */
  1073.  
  1074. static void
  1075. singleStripeIODoneProc(IOControlPtr, status, amountTransferred)
  1076.     RaidIOControl    *IOControlPtr;
  1077.     ReturnStatus       status;
  1078.     int               amountTransferred;
  1079. {
  1080.     MASTER_LOCK(&IOControlPtr->mutex);
  1081.     IOControlPtr->amountTransferred += amountTransferred;
  1082.  
  1083.     /*
  1084.      * A Raid IO operation fails if any of the component operations fail.
  1085.      * Therefore, don't overwrite status if a previous operation has failed.
  1086.      */
  1087.     if (IOControlPtr->status == SUCCESS) {
  1088.         IOControlPtr->status = status;
  1089.     }
  1090.  
  1091.     /*
  1092.      * Check if all component IO's done.
  1093.      */
  1094.     IOControlPtr->numIO--;
  1095.     if (IOControlPtr->numIO == 0) {
  1096.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1097.         IOControlPtr->doneProc(IOControlPtr->clientData,
  1098.         IOControlPtr->status, IOControlPtr->amountTransferred);
  1099.     Raid_FreeIOControl(IOControlPtr);
  1100.     Raid_EndUse(IOControlPtr->raidPtr);
  1101.     } else {
  1102.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1103.     }
  1104. }
  1105.  
  1106.  
  1107. /*
  1108.  *----------------------------------------------------------------------
  1109.  *
  1110.  * Raid_InitiateSimpleStripeIOs --
  1111.  *
  1112.  *    Breaks up IO requests in stripes and then initiates them.
  1113.  *    This procedure is used when the RAID device is configured without
  1114.  *    parity.
  1115.  *
  1116.  * Results:
  1117.  *    None.
  1118.  *
  1119.  * Side effects:
  1120.  *    The IO operation.
  1121.  *
  1122.  *----------------------------------------------------------------------
  1123.  */
  1124.  
  1125. static void simpleStripeIODoneProc();
  1126.  
  1127. void 
  1128. Raid_InitiateSimpleStripeIOs(raidPtr, operation, firstSector, nthSector,
  1129.                 buffer, doneProc, clientData, ctrlData)
  1130.     Raid       *raidPtr;
  1131.     int        operation;
  1132.     unsigned     firstSector, nthSector;
  1133.     Address      buffer;
  1134.     void      (*doneProc)();
  1135.     ClientData    clientData;
  1136.     int         ctrlData;
  1137. {
  1138.     RaidIOControl       *IOControlPtr;
  1139.     DevBlockDeviceRequest *devReqPtr;
  1140.     int            numSectorsToTransfer;
  1141.     unsigned            currentSector;
  1142.     unsigned            diskSector;
  1143.     int               col, row;
  1144.  
  1145.     /*
  1146.      * Break up entire IO request into stripe units.
  1147.      */
  1148.     IOControlPtr = Raid_MakeIOControl(doneProc, clientData);
  1149.     IOControlPtr->numIO++;
  1150.     currentSector = firstSector;
  1151.     while ( currentSector < nthSector ) {
  1152.         numSectorsToTransfer = MIN( raidPtr->sectorsPerStripeUnit -
  1153.                 currentSector%raidPtr->sectorsPerStripeUnit,
  1154.                 nthSector - currentSector );
  1155.     Raid_MapSector(raidPtr, currentSector, &col, &row, &diskSector);
  1156.     devReqPtr = Raid_MakeBlockDeviceRequest(raidPtr, operation,
  1157.         diskSector, numSectorsToTransfer, buffer,
  1158.         simpleStripeIODoneProc, (ClientData) IOControlPtr, ctrlData);
  1159.  
  1160.         MASTER_LOCK(&IOControlPtr->mutex);
  1161.     IOControlPtr->numIO++;
  1162.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1163.  
  1164.         (void) Dev_BlockDeviceIO(raidPtr->disk[col][row]->handlePtr, devReqPtr);
  1165.  
  1166.         currentSector += numSectorsToTransfer;
  1167.     buffer += SectorToByte(raidPtr, numSectorsToTransfer);
  1168.     }
  1169.  
  1170.     MASTER_LOCK(&IOControlPtr->mutex);
  1171.     IOControlPtr->numIO--;
  1172.     if (IOControlPtr->numIO == 0) {
  1173.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1174.         IOControlPtr->doneProc(IOControlPtr->clientData,
  1175.         IOControlPtr->status, IOControlPtr->amountTransferred);
  1176.     Raid_FreeIOControl(IOControlPtr);
  1177.     } else {
  1178.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1179.     }
  1180. }
  1181.  
  1182.  
  1183. /*
  1184.  *----------------------------------------------------------------------
  1185.  *
  1186.  * simpleStripeIODoneProc --
  1187.  *
  1188.  *    Callback procedure for Raid_InitiateSimpleStripeIOs.
  1189.  *
  1190.  * Results:
  1191.  *    None.
  1192.  *
  1193.  * Side effects:
  1194.  *    Reports errors.
  1195.  *    Calls callback procedure.
  1196.  *
  1197.  *----------------------------------------------------------------------
  1198.  */
  1199.  
  1200. static void
  1201. simpleStripeIODoneProc(devReqPtr, status, amountTransferred)
  1202.     DevBlockDeviceRequest *devReqPtr;
  1203.     ReturnStatus       status;
  1204.     int               amountTransferred;
  1205. {
  1206.     RaidIOControl    *IOControlPtr = (RaidIOControl *) devReqPtr->clientData;
  1207.  
  1208.     Raid_FreeBlockDeviceRequest(devReqPtr);
  1209.  
  1210.     MASTER_LOCK(&IOControlPtr->mutex);
  1211.     IOControlPtr->amountTransferred += amountTransferred;
  1212.  
  1213.     /*
  1214.      * A Raid IO operation fails if any of the component operations fail.
  1215.      * Therefore, don't overwrite status if a previous operation has failed.
  1216.      */
  1217.     if (IOControlPtr->status == SUCCESS) {
  1218.         IOControlPtr->status = status;
  1219.     }
  1220.  
  1221.     /*
  1222.      * Check if all component IO's done.
  1223.      */
  1224.     IOControlPtr->numIO--;
  1225.     if (IOControlPtr->numIO == 0) {
  1226.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1227.         IOControlPtr->doneProc(IOControlPtr->clientData,
  1228.         IOControlPtr->status, IOControlPtr->amountTransferred);
  1229.     Raid_FreeIOControl(IOControlPtr);
  1230.     } else {
  1231.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1232.     }
  1233. }
  1234.